package com.phonebook.util;

import com.phonebook.constant.JwtConstant;
import com.phonebook.entity.CheckResult;
import com.phonebook.enums.CheckResultEnum;
import io.jsonwebtoken.*;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;

/**
 * jwt加密和解密的工具类
 *
 * @author 高旭
 * @date 2021-04-24
 */
public class JwtUtils {

    /**
     * 生成jwt
     *
     * @param id 用户id
     * @param subject   一般是用户名
     * @param timeout   token有效期
     * @return
     */
    public static String createJWT(String id, String subject, long timeout) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主题
                .setIssuer("Java1234")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, generalKey()); // 签名算法以及密匙
        if (timeout >= 0) {
            long expMillis = nowMillis + timeout;
            Date expDate = new Date(expMillis);
            builder.setExpiration(expDate); // 过期时间
        }
        return builder.compact();
    }

    /**
     * 验证jwt
     *
     * @param jwt
     * @return
     */
    public static CheckResult validateJWT(String jwt) {
        CheckResult checkResult = new CheckResult();
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(generalKey())   //秘钥
                    .parseClaimsJws(jwt)     //JWT字符串
                    .getBody();
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setSuccess(false);
            checkResult.setErrCode(CheckResultEnum.EXPIRE.getCode());
            checkResult.setMessage(CheckResultEnum.EXPIRE.getMessage());
        } catch (SignatureException e) {
            checkResult.setSuccess(false);
            checkResult.setErrCode(CheckResultEnum.FAIL.getCode());
            checkResult.setMessage(CheckResultEnum.FAIL.getMessage());
        } catch (Exception e) {
            checkResult.setSuccess(false);
            checkResult.setErrCode(CheckResultEnum.NULL.getCode());
            checkResult.setMessage(CheckResultEnum.NULL.getMessage());
        }
        return checkResult;
    }


    /**
     * 生成加密Key
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(JwtConstant.JWT_SECERT);
        SecretKey secretKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return secretKey;
    }





    /**
     * 测试
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        // 生成token
        String sc = createJWT("1", "jack", JwtConstant.JWT_TTL);
        System.out.println(sc);

        // 验证token
        CheckResult checkResult = validateJWT(sc);
        System.out.println(checkResult.isSuccess());
        System.out.println(checkResult.getErrCode());
        Claims claims = checkResult.getClaims();
        System.out.println(claims);
        System.out.println(claims.getId());
        System.out.println(claims.getSubject());

        // 刷新token，即重新生成token
        Claims claims2 = validateJWT(sc).getClaims();
        String sc2 = createJWT(claims2.getId(), claims2.getSubject(), JwtConstant.JWT_TTL);
        System.out.println(sc2);
    }

}
